package openglsuperbible.Chapter6;

import de.matthiasmann.twl.utils.PNGDecoder;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import openglsuperbible.glutils.GLBatch;
import openglsuperbible.glutils.Shader;
import openglsuperbible.glutils.SimpleGLBatch;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.*;
import static org.lwjgl.opengl.GL30.*;

/**
 *
 * @author Matthew
 */
public class TexturedTriangle {
     public static final int DISPLAY_HEIGHT = 600;
        public static final int DISPLAY_WIDTH = 800;
        
        private GLBatch triangleBatch;
        private Shader shaderIdentity;                           
        private int texture;
        
        public void resizeGL() {   
            glViewport(0,0,DISPLAY_WIDTH ,DISPLAY_HEIGHT); 
        } 

        /**
         * Initialize anything need for the rendering context
         */
        public void initGL() {   
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);     // blue background
           
        shaderIdentity = new Shader("TexturedIdentity","TexturedIdentity");
               
        glEnable(GL_TEXTURE_2D);  
        
        float[] verts ={-0.5f, 0.0f, 0.0f, 1.0f,    // vertex array  x,y,z,w  
                         0.5f, 0.0f, 0.0f, 1.0f,            
                         0.0f, 0.5f, 0.0f, 1.0f};
        

        float[] texcoords = { 0.0f, 0.0f,// tex coords
		              1.0f, 0.0f,
                              0.5f, 1.0f };
        short[] index = {0, 1, 2};
           
            triangleBatch = new SimpleGLBatch(GL_TRIANGLES,
                    verts, 
                    null,//color
                    null,// normal 
                    texcoords,
                    index); // the index of the vertex    
                        
             texture = loadTexture("stone3",GL_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE);


        }   

 
        /**
         * Clear the buffers.
         * Set the shader uniforms.
         * Draw the batch
         * Flip the buffers.
         */
        public void render() {

            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
            shaderIdentity.use();        
//            glActiveTexture(GL_TEXTURE0);
            glBindTexture(GL_TEXTURE_2D, texture);
            shaderIdentity.setUniform1i("colorMap", 0);
            triangleBatch.draw(shaderIdentity.getAttributeLocations());
            shaderIdentity.endUse(); 
 
            Display.update();  
        }   
            

        /**
         * Creates a window with an OpenGL context.
         */   
        public void create()  { 
            try{
            //Display    
            Display.setDisplayMode(new DisplayMode(DISPLAY_WIDTH,DISPLAY_HEIGHT)); 
            Display.setFullscreen(false);
            Display.setTitle("Textured Triangle");
            Display.create();            
                               
            //Keyboard         
            Keyboard.create();   
            //Mouse          
            Mouse.setGrabbed(false);
            Mouse.create(); 
            
            } catch (LWJGLException e) {
                
		System.exit(0);
	    }
            
            
            //OpenGL      
            initGL();    
            resizeGL();  
        }  
        
        /**
         * The game loop
         */
        public void run() 
        {
            while (!Display.isCloseRequested() && !Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {              
        
                render();

                Display.sync(60);
                Display.setVSyncEnabled(true);
            }

        }
        
        /**
         * Clean up any used resources.
         */
        public void destroy() {  
            //Methods already check if created before destroying.  
            Mouse.destroy();   
            Keyboard.destroy();
            Display.destroy();     
        } 
        
        /**
         * The main method for the program.
         * @param args 
         */
       public static void main(String[] args) {
            TexturedTriangle main = new TexturedTriangle(); 
            main.create(); 
            main.run();

            if(main != null) {  
                main.destroy();
            }                
        }  
       
       
       private int loadTexture(String filename, int minFilter, int magFilter, int wrapMode){
            
            InputStream in;
            int texID = glGenTextures();
            try {
                in = new FileInputStream("textures/" + filename + ".png");
                PNGDecoder decoder = new PNGDecoder(in);
                int width = decoder.getWidth();
                int height = decoder.getHeight();
                
                ByteBuffer buffer = BufferUtils.createByteBuffer(4 * width * height);
                decoder.decode(buffer, width * 4, PNGDecoder.Format.RGBA);          
                buffer.flip();
                in.close();
                
                glBindTexture(GL_TEXTURE_2D, texID);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
                
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
                
                glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
                glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);

//                             
                if(minFilter == GL_LINEAR_MIPMAP_LINEAR || 
                    minFilter == GL_LINEAR_MIPMAP_NEAREST ||
                     minFilter == GL_NEAREST_MIPMAP_LINEAR ||
                     minFilter == GL_NEAREST_MIPMAP_NEAREST){
                glGenerateMipmap(GL_TEXTURE_2D);}       
                glBindTexture(GL_TEXTURE_2D, 0);
                
            } catch (FileNotFoundException e) {
                System.err.println("Failed to find the texture file: " + filename + ".png");
                
            } catch (IOException ex) {
                System.err.println("Error reading file: " + filename + ".png");
                
            } 
           
            return texID;
        }
            
}
